#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include "absl/memory/memory.h"
#include "absl/types/optional.h"
#include "api/audio/audio_mixer.h"
#include "api/audio_codecs/audio_decoder_factory.h"
#include "api/audio_codecs/audio_encoder_factory.h"
#include "api/audio_codecs/builtin_audio_decoder_factory.h"
#include "api/audio_codecs/builtin_audio_encoder_factory.h"
#include "api/audio_options.h"
#include "api/create_peerconnection_factory.h"
#include "api/rtp_sender_interface.h"
#include "api/video_codecs/builtin_video_decoder_factory.h"
#include "api/video_codecs/builtin_video_encoder_factory.h"
#include "api/video_codecs/video_decoder_factory.h"
#include "api/video_codecs/video_encoder_factory.h"
#include "modules/audio_device/include/audio_device.h"
#include "modules/audio_processing/include/audio_processing.h"
#include "modules/video_capture/video_capture.h"
#include "modules/video_capture/video_capture_factory.h"
#include "p2p/base/port_allocator.h"
#include "pc/video_track_source.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "rtc_base/ref_counted_object.h"
#include "rtc_base/rtc_certificate_generator.h"
#include <QMainWindow>
#include "api/video/i420_buffer.h"
#include "signal_client.h"
#include <QStandardItemModel>
#include "Qss.h"

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE


class VideoRenderer : public QObject,
        public rtc::VideoSinkInterface<webrtc::VideoFrame>

{
Q_OBJECT
public:
    VideoRenderer(
                int width,
                int height,
                webrtc::VideoTrackInterface* track_to_render);
    virtual ~VideoRenderer();

    void Lock() { ::EnterCriticalSection(&buffer_lock_); }

    void Unlock() { ::LeaveCriticalSection(&buffer_lock_); }

    // VideoSinkInterface implementation
    void OnFrame(const webrtc::VideoFrame& frame) override;

    const BITMAPINFO& bmi() const { return bmi_; }
    const uint8_t* image() const { return image_; }


signals:
    void rgbadata(uint8_t *data,uint64_t len);
    void UpdateFrame(rtc::scoped_refptr<webrtc::I420BufferInterface>& buffer);
    void NotifySize(uint32_t width,uint32_t height);
protected:
    void SetSize(int width, int height);

    enum {
        SET_SIZE,
        RENDER_FRAME,
    };

    HWND wnd_;
    BITMAPINFO bmi_;
    uint8_t* image_;
    CRITICAL_SECTION buffer_lock_;
    rtc::scoped_refptr<webrtc::VideoTrackInterface> rendered_track_;
};

// A little helper class to make sure we always to proper locking and
// unlocking when working with VideoRenderer buffers.
template <typename T>
class AutoLock {
 public:
  explicit AutoLock(T* obj) : obj_(obj) { obj_->Lock(); }
  ~AutoLock() { obj_->Unlock(); }

 protected:
  T* obj_;
};

class WebrtcHanlder :public QObject,
        public webrtc::PeerConnectionObserver,
        public webrtc::CreateSessionDescriptionObserver{
    Q_OBJECT
signals:
    void OnOfferSdp(QString);
    void OnRemoteTrack(webrtc::MediaStreamTrackInterface*);
    void OnConectionDisconnected();
    void OnConectionComplete();

public:
    WebrtcHanlder();
    int InitWebrtc();
    void SetSignalClient(SignalClient *);
    void CreateOffer();
    void CreateAnswer();
    void SetRemotePeerName(QString remote);
    void SetRemoteSdp(QString);
    void SetRemoteCandidate(QString);
    void CreateAnwer();
    webrtc::VideoTrackInterface *VideoTrack();
    void AddLocalTrack();


protected:
    ~WebrtcHanlder();
    //
    // PeerConnectionClientObserver implementation.
    //
    void OnSignalingChange(
        webrtc::PeerConnectionInterface::SignalingState new_state) override;
    void OnAddTrack(rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver,
        const std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>>&
            streams) override;
    void OnRemoveTrack(
        rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver) override;
    void OnDataChannel(
        rtc::scoped_refptr<webrtc::DataChannelInterface> channel) override;
    void OnRenegotiationNeeded() override {}
    void OnIceConnectionChange(
        webrtc::PeerConnectionInterface::IceConnectionState new_state) override;
    void OnIceGatheringChange(
        webrtc::PeerConnectionInterface::IceGatheringState new_state) override;
    void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) override;
    void OnIceConnectionReceivingChange(bool receiving) override;
    // CreateSessionDescriptionObserver
    void OnSuccess(webrtc::SessionDescriptionInterface* desc) override;
    void OnFailure(webrtc::RTCError error) override;

private:
    rtc::scoped_refptr<webrtc::PeerConnectionInterface> m_peer_connection_;
    rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface>
        m_peer_connection_factory_;
    SignalClient *mClient;
    QString mRemoteName;
    webrtc::VideoTrackInterface *mVideoTrack;
    webrtc::AudioTrackInterface *mAudioTrack;
};

class MainWindow :public QssMainWindow
{
    Q_OBJECT
public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
protected:

private slots:
    void on_pushButton_clicked();
    void signal_conneted();
    void on_pushButton_2_clicked();
    void signal_closed();
    void signal_response(int,QJsonObject);
    void itemClicked(QModelIndex);
    void on_local_sdp(QString);
    void on_track_add(webrtc::MediaStreamTrackInterface*);
    void on_notify_size(uint32_t,uint32_t);
    void on_pushButton_3_clicked();

    void on_pushButton_4_clicked();

    void on_pushButton_5_clicked();

    void on_pushButton_6_clicked();

private:
    Ui::MainWindow *ui;
    rtc::scoped_refptr<WebrtcHanlder> mHandler;
    SignalClient *mSignalClient;
    QStandardItemModel *mModel;
    QString mPeerName;
    QString mRemoteName;
    bool mCalling;
    std::unique_ptr<VideoRenderer> local_renderer_;
    std::unique_ptr<VideoRenderer> remote_renderer_;
    webrtc::VideoTrackInterface* mRemoteVideoTrack;
    webrtc::VideoTrackInterface* mLocalVideoTrack;

};
#endif // MAINWINDOW_H
